using System;
using System.Linq;
using System.Reflection;
using System.Text;

namespace BindingFlagsSnippet
{
    public abstract class A
    {
        public abstract int TestA { get; set; }
        public virtual int TestB { get; set; }
        public virtual int TestC { get; set; }

        public class MyClass : A
        {
            public int a { get; set; }
            internal int b { get; set; }
            protected int c { get; set; }
            protected internal int d { get; set; }
            private int e { get; set; }
            public static float f { get; set; } = 1;
            public override int TestA { get; set; }
            public override int TestB { get => base.TestB; set => base.TestB = value; }
            new public int TestC { get => base.TestC; set => base.TestC = value; }
        }

        class Example
        {
            static void Main()
            {
                Type type = typeof(MyClass);
                PropertyInfo[] methods = type.GetProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.Instance);

                foreach (PropertyInfo item in methods)
                {
                    StringBuilder builder = new StringBuilder();
                    builder.Append(GetVisibility(item) + " ");
                    builder.Append(item.GetGetMethod(true).IsStatic ? "static " : string.Empty);
                    builder.Append(IsOver(type, item) + " ");
                    builder.Append(item.PropertyType + " ");
                    builder.Append(item.Name + " ");
                    builder.Append(GetConstructor(item));
                    Console.WriteLine(builder.ToString());
                }
                Console.ReadKey();
            }
            public static string GetVisibility(PropertyInfo property)
            {
                MethodInfo method = property.GetGetMethod(true);
                return
                    method.IsPublic ? "public" :
                    method.IsPrivate ? "private" :
                    method.IsAssembly ? "internal" :
                    method.IsFamily ? "protected" :
                    method.IsFamilyOrAssembly ? "protected internal" :
                    null;
            }

            // virtual override  abstract new
            public static string IsOver(Type type, PropertyInfo property)
            {
                MethodInfo method = property.GetGetMethod(true);
                // 没有相应的信息，说明没有使用以上关键字修饰
                if (!method.IsHideBySig)
                    return string.Empty;

                // 是否抽象方法
                if (method.IsAbstract)
                    return "abstract";

                // virtual、override、实现接口的方法
                if (method.IsVirtual)
                {
                    // 实现接口的方法
                    if (method.IsFinal)
                        return string.Empty;
                    // 没有被重写，则为 virtual
                    if (method.Equals(method.GetBaseDefinition()))
                        return "virtual";
                    else
                        return "override";
                }
                // new
                else
                {
                    // 如果是当前类型中定义的方法，则只是一个普通的方法
                    if (type == method.DeclaringType)
                        return string.Empty;

                    return "new";
                }
            }

            // 解析属性的构造器
            public static string GetConstructor(PropertyInfo property)
            {
                string str = "{ ";
                if (property.CanRead)
                    str += "get; ";
                if (property.CanWrite)
                    str += "set; ";
                str += "}";
                return str;
            }
        }
    }
}